package com.question.business.user.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.question.business.user.entity.User;
import com.question.business.user.mapper.UserMapper;
import com.question.business.user.model.ao.*;
import com.question.business.user.model.dto.UserCacheDTO;
import com.question.business.user.model.vo.*;
import com.question.business.user.service.*;
import com.question.common.constants.NumberConstants;
import com.question.common.enums.YesAndNoEnum;
import com.question.common.exception.BusinessException;
import com.question.common.properties.SystemConfigProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 用户服务实现类
 *
 * @author star
 * @since 2022-07-20
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private SystemConfigProperties configProperties;

    private IUserRoleService userRoleService;

    private IUserPostService userPostService;

    private IUserDeptService userDeptService;

    private IUserOrgService userOrgService;

    /**
     * 用户分页查询
     *
     * @param ao 请求参数
     * @return Page<UserVO> 响应参数
     */
    @Override
    public Page<UserVO> queryUserPage(UserPageAO ao) {
        return baseMapper.queryUserPage(ao.createPage(), ao);
    }

    /**
     * 用户明细查询
     *
     * @param id 用户ID
     * @return UserDetailVO 响应参数
     */
    @Override
    public UserDetailVO queryUserDetail(String id) {
        User entity = super.getById(id);
        if (Objects.nonNull(entity)) {
            UserDetailVO vo = new UserDetailVO();
            BeanUtils.copyProperties(entity, vo);
            vo.setRoleIds(userRoleService.queryRoleByUserId(vo.getId()));
            vo.setPostIds(userPostService.queryPostByUserId(vo.getId()));
            vo.setDeptIds(userDeptService.queryDeptByUserId(vo.getId()));
            vo.setOrgIds(userOrgService.queryOrgByUserId(vo.getId()));
            return vo;
        }
        return null;
    }

    /**
     * 用户新增数据
     *
     * @param ao 请求参数
     * @return UserAddVO 响应参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserAddVO addUser(UserAddAO ao) {
        if (!ao.getPassword().equals(ao.getConfirmPassword())) {
            throw new BusinessException("密码与确认密码不一致");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getUsername, ao.getUsername());
        boolean isExist = SqlHelper.retBool(super.count(queryWrapper));
        if (isExist) {
            throw new BusinessException("用户名已存在");
        }
        // 新增用户
        User entity = new User();
        BeanUtils.copyProperties(ao, entity);
        super.save(entity);
        userRoleService.addUserRole(entity.getId(), ao.getRoleIds());
        userPostService.addUserPost(entity.getId(), ao.getPostIds());
        userDeptService.addUserDept(entity.getId(), ao.getDeptIds());
        userOrgService.addUserOrg(entity.getId(), ao.getOrgIds());
        UserAddVO vo = new UserAddVO();
        vo.setId(entity.getId());
        return vo;
    }

    /**
     * 用户修改数据
     *
     * @param ao 数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUser(UserUpdateAO ao) {
        if (ao.getId().equals(ao.getParentId())) {
            throw new BusinessException("直属上级不能是自己");
        }
        User entity = new User();
        BeanUtils.copyProperties(ao, entity);
        super.updateById(entity);
        userRoleService.addUserRole(entity.getId(), ao.getRoleIds());
        userPostService.addUserPost(entity.getId(), ao.getPostIds());
        userDeptService.addUserDept(entity.getId(), ao.getDeptIds());
        userOrgService.addUserOrg(entity.getId(), ao.getOrgIds());
    }

    /**
     * 用户删除数据
     *
     * @param id 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteUser(String id) {
        super.removeById(id);
        userRoleService.addUserRole(id, null);
        userPostService.addUserPost(id, null);
        userDeptService.addUserDept(id, null);
        userOrgService.addUserOrg(id, null);
    }

    /**
     * 用户批量删除数据
     *
     * @param ids 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchUser(List<String> ids) {
        super.removeBatchByIds(ids);
        for (String id : ids) {
            userRoleService.addUserRole(id, null);
            userPostService.addUserPost(id, null);
            userDeptService.addUserDept(id, null);
            userOrgService.addUserOrg(id, null);
        }
    }

    /**
     * 用户导出数据
     *
     * @param ao     请求参数
     * @param stream 输出流
     */
    @Override
    public void exportUser(UserPageAO ao, ServletOutputStream stream) {
        ao.setSize(-1);
        List<UserVO> vos = queryUserPage(ao).getRecords();
        List<UserExcelVO> list = new ArrayList<>(vos.size());
        for (UserVO vo : vos) {
            UserExcelVO excelVo = new UserExcelVO();
            BeanUtils.copyProperties(vo, excelVo);
            list.add(excelVo);
        }

        ExcelWriter excelWriter = EasyExcelFactory.write(stream).build();
        excelWriter.write(list, EasyExcelFactory.writerSheet(NumberConstants.ZERO).head(UserExcelVO.class).build());
        excelWriter.finish();
    }

    /**
     * 根据用户名称查询用户信息
     *
     * @param username 用户名称
     * @return User
     */
    @Override
    public User queryUserByUsername(String username) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(User::getEnabled, YesAndNoEnum.YES.getCode())
                .eq(User::getUsername, username);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 查询用户缓存
     *
     * @return Map<String, UserCacheDTO>
     */
    @Override
    public Map<String, UserCacheDTO> queryUserCache() {
        return baseMapper.queryUserCache();
    }

    /**
     * 用户类型启用、停用
     *
     * @param ao 数据
     */
    @Override
    public void enableUser(UserEnabledAO ao) {
        this.lambdaUpdate().eq(User::getId, ao.getId()).set(User::getEnabled, ao.getEnabled()).update(new User());
    }

    /**
     * 根据用户名称更新错误次数
     *
     * @param username 用户名称
     */
    @Override
    public void changeLoginErrorNumber(String username) {
        baseMapper.changeLoginErrorNumber(username);
    }

    /**
     * 根据用户id解锁
     *
     * @param id 用户ID
     */
    @Override
    public void unlockUser(String id) {
        baseMapper.unlockUser(id);
    }

    /**
     * 用户下拉列表查询
     *
     * @param ao 请求参数
     * @return List<UserDropDownVO> 响应参数
     */
    @Override
    public List<UserDropDownVO> queryUserDropDown(UserDropDownAO ao) {
        return baseMapper.queryUserDropDown(ao);
    }

    /**
     * 用户重置密码
     *
     * @param ao 请求参数
     */
    @Override
    public void resetUserPassword(UserResetPasswordAO ao) {
        this.lambdaUpdate().eq(User::getId, ao.getId()).set(User::getPassword, configProperties.getDefaultPassword()).update(new User());
    }

}